package main

import (
	"fmt"
	"net"
	"os"
	"strings"
	"time"
)

const (
	defaultBitRate              int           = 2 * 1024 * 1024
	defaultDelayTimeUsPerSecond time.Duration = 50 * 1000
	defaultSleepTimesPerSecond  time.Duration = 1
)

var (
	protoHeadSize int
	mediaHeadSize int
)

func checkError(err error) {
	if err != nil {
		fmt.Println("error:", err.Error())
		os.Exit(1)
	}
}

func createPackageSend(sendXmlRealData *[]byte, cmd uint16, conn *net.Conn) {
	sendXmlHead := xmlHead
	sendXmlData := []byte(sendXmlHead + string(*sendXmlRealData))

	bodySize := len(sendXmlData)
	head := ProtoHeadType{tcpPackageStartTag, tcpPackageprotoVersion, cmd, uint16(bodySize)}
	sendPackage := make([]byte, protoHeadSize+bodySize)
	headSlice := make([]byte, protoHeadSize)
	headSlice[0] = byte(head.tag & 0x00FF)
	headSlice[1] = byte((head.tag >> 8) & 0x00FF)
	headSlice[2] = byte(head.version & 0x00FF)
	headSlice[3] = byte((head.version >> 8) & 0x00FF)
	headSlice[4] = byte(head.cmd & 0x00FF)
	headSlice[5] = byte((head.cmd >> 8) & 0x00FF)
	headSlice[6] = byte(head.bodySize & 0x00FF)
	headSlice[7] = byte((head.bodySize >> 8) & 0x00FF)
	copy(sendPackage, headSlice[0:protoHeadSize])
	copy(sendPackage[len(headSlice):], sendXmlData[0:])

	_, err := (*conn).Write(sendPackage)
	if err != nil {
		fmt.Println("send back xml package fail ! cmd =", head.cmd)
		return
	}

	fmt.Printf("sendPackage: len=%d, %x,%x,%x,%x,%d,%d,%x,%x\n", len(sendPackage), sendPackage[0], sendPackage[1], sendPackage[2], sendPackage[3], sendPackage[4], sendPackage[5], sendPackage[6], sendPackage[7])
	fmt.Println(string(sendPackage[protoHeadSize:]))
}

func isMacEqual(a *MacType, b *MacType) bool {
	for i := 0; i < int(macAddrBytes); i++ {
		if a[i] != b[i] {
			//fmt.Println("isMacEqual false !")
			return false
		}
	}

	//fmt.Println("isMacEqual true !")
	return true
}

func isUdpAddrEqual(a *net.UDPAddr, b *net.UDPAddr) bool {
	c := a.String()
	d := b.String()
	//fmt.Println("c=", c, "d=", d)
	ret := strings.Compare(c, d)
	if ret == 0 {
		return true
	} else {
		return false
	}
}

func getMacFromBytesSlice(inData []byte) MacType {
	//fmt.Println("getMacFromBytesSlice:inData=", inData)
	var mac MacType
	for i := 0; i < int(macAddrBytes-1); i++ {
		mac[i] = inData[i]
	}
	mac[macAddrBytes-1] = 0

	return mac
}

func checkKeyequal(key *KeyType, mac *MacType, streamId int) int {
	var diff int
	for i := 0; i < macAddrBytes-1; i++ {
		diff = int(key[i]) - int(mac[i])
		if diff != 0 {
			return diff
		}
	}

	diff = int(key[macAddrBytes-1]-'0') - streamId
	return diff
}

func checkKeyequalEx(key *KeyType, mac *MacType) int {
	var diff int
	for i := 0; i < macAddrBytes-1; i++ {
		diff = int(key[i]) - int(mac[i])
		if diff != 0 {
			return diff
		}
	}

	return diff
}

func setKeyValue(key *KeyType, mac *MacType, streamId int) {
	for i := 0; i < macAddrBytes-1; i++ {
		key[i] = mac[i]
	}
	key[macAddrBytes-1] = byte(streamId) + '0'
}

func stoi(str string) int {
	i := int(str[0] - '0')
	return i
}

func sendSpeedCtrlMethod(pCtrl *SendSpeedCtrlInfoType, sendSize int) {
	if pCtrl.byteRatePerSecond == 0 || sendSize <= 0 {
		return
	}

	pCtrl.totalSendBytes += uint64(sendSize)
	if pCtrl.totalSendBytes >= pCtrl.nextSleepSendBytes {
		time.Sleep(pCtrl.sleepTimeUsPerTime * time.Microsecond)
		pCtrl.nextSleepSendBytes += pCtrl.sleepOneTimeSendBytes
	}
}

func initSendSpeedCtrlPara(pCtrl *SendSpeedCtrlInfoType, bitRate int) {
	if pCtrl.byteRatePerSecond == 0 || bitRate <= 0 {
		return
	}

	pCtrl.byteRatePerSecond = bitRate / 8
	pCtrl.delayTimeUsPerSecond = defaultDelayTimeUsPerSecond
	pCtrl.sleepTimesPerSecond = defaultSleepTimesPerSecond
	pCtrl.sleepOneTimeSendBytes = uint64(pCtrl.byteRatePerSecond) / uint64(pCtrl.sleepTimesPerSecond)
	pCtrl.sleepTimeUsPerTime = pCtrl.delayTimeUsPerSecond / pCtrl.sleepTimesPerSecond
	pCtrl.totalSendBytes = 0
	pCtrl.nextSleepSendBytes = pCtrl.totalSendBytes + pCtrl.sleepOneTimeSendBytes
}

func getMediaHeadStructFromSlice(slice []byte) MediaHeadType {
	//fmt.Println("getMediaHeadStructFromSlice:len=", len(slice))
	var mediaHead MediaHeadType
	mediaHead.mac = getMacFromBytesSlice(slice[0:macAddrBytes])
	mediaHead.streamId = changeFourBytesIntoInt(slice[macAddrBytes+0 : macAddrBytes+4])
	mediaHead.timeStamp = changeFourBytesIntoUInt32(slice[macAddrBytes+4 : macAddrBytes+8])
	mediaHead.frameIndex = changeFourBytesIntoUInt32(slice[macAddrBytes+8 : macAddrBytes+12])
	mediaHead.frameSize = changeFourBytesIntoUInt32(slice[macAddrBytes+12 : macAddrBytes+16])
	mediaHead.totalFragmentNumber = changeFourBytesIntoUInt16(slice[macAddrBytes+16 : macAddrBytes+18])
	mediaHead.fragmentNumber = changeFourBytesIntoUInt16(slice[macAddrBytes+18 : macAddrBytes+20])

	return mediaHead
}

func changeFourBytesIntoInt(slice []byte) int {
	return ((int(slice[0]) << 0) & 0x000000FF) |
		((int(slice[1]) << 8) & 0x0000FF00) |
		((int(slice[1]) << 16) & 0x00FF0000) |
		((int(slice[1]) << 24) & 0xFF000000)
}

func changeFourBytesIntoUInt32(slice []byte) uint32 {
	return ((uint32(slice[0]) << 0) & 0x000000FF) |
		((uint32(slice[1]) << 8) & 0x0000FF00) |
		((uint32(slice[1]) << 16) & 0x00FF0000) |
		((uint32(slice[1]) << 24) & 0xFF000000)
}

func changeFourBytesIntoUInt16(slice []byte) uint16 {
	return ((uint16(slice[0]) << 0) & 0x00FF) |
		((uint16(slice[1]) << 8) & 0xFF00)
}

func getCurTimeMs() int64 {
	cur := time.Now()
	ms := cur.UnixNano() / 1000000
	return ms
}
